#include "Balance.h"
#include "rtwtypes.h"
#include "calPrms.h"
#include "Balance_private.h"

#define Balance_IN_BalanceOff          ((uint8_T)1U)
#define Balance_IN_BalanceOn           ((uint8_T)2U)

void Balance(const boolean_T *rtu_Balance_Ena, const uint16_T
             rtu_Cell_Voltage_mV[32], const uint16_T *rtu_CellV_min, const
             uint16_T *rtu_CellV_max, const int16_T *rtu_CellT_Max, const
             int16_T *rtu_CellT_Min, const int16_T *rtu_PCB_T_Max, const int16_T
             *rtu_PCB_T_Min, const uint8_T *rtu_CollectChip_Temperature_Fla,
             const boolean_T *rtu_Flag_Charge, const uint8_T
             *rtu_Flag_Communication, const real32_T *rtu_SOC_ACT, const uint8_T
             *rtu_Bala_Diag, const uint32_T *rtu_Balance_State, const boolean_T
             rtu_CellVConnect_flg[32], uint8_T *rty_Bal_State, uint8_T
             rty_Flag_Balance[32], uint32_T *rty_EN_Balance, B_Balance_c_T
             *localB, DW_Balance_f_T *localDW)
{
  int32_T i;
  uint16_T rtb_Add;
  int8_T rtb_Bal_Cmd[32];
  boolean_T rtb_LogicalOperator5_a[32];
  boolean_T rtb_LogicalOperator10;
  boolean_T rtb_RelationalOperator;
  boolean_T rtb_RelationalOperator10;
  boolean_T rtb_RelationalOperator2;
  boolean_T rtb_RelationalOperator3;
  boolean_T rtb_RelationalOperator5;
  boolean_T rtb_RelationalOperator6;
  boolean_T rtb_RelationalOperator7;
  boolean_T rtb_RelationalOperator8;
  rtb_Add = (uint16_T)(*rtu_CellV_max - *rtu_CellV_min);
  rtb_RelationalOperator = (rtb_Add >= Threshold_DiffVoltage);
  localDW->Relay1_Mode = ((*rtu_CellT_Max >= Cell_maxTemp) || ((*rtu_CellT_Max >
    (int16_T)(Cell_maxTemp - 3)) && localDW->Relay1_Mode));
  localDW->Relay2_Mode = ((*rtu_CellT_Min >= Cell_minTemp) || ((*rtu_CellT_Min >
    (int16_T)(Cell_minTemp - 3)) && localDW->Relay2_Mode));
  localDW->Relay_Mode = ((*rtu_PCB_T_Max >= PCB_maxTemp) || ((*rtu_PCB_T_Max >
    PCB_TempRec_Balance) && localDW->Relay_Mode));
  rtb_RelationalOperator8 = (*rtu_PCB_T_Min > PCB_minTemp);
  rtb_RelationalOperator8 = ((!localDW->Relay_Mode) && rtb_RelationalOperator8);
  rtb_LogicalOperator10 = (*rtu_CollectChip_Temperature_Fla == 0);
  rtb_RelationalOperator5 = (*rtu_Flag_Communication == 0);
  rtb_RelationalOperator6 = (*rtu_SOC_ACT <= SOC_CAL - 4.0F);
  rtb_RelationalOperator7 = (*rtu_CellV_max < (uint16_T)(CellV_limit - 20U));
  rtb_RelationalOperator2 = (*rtu_Bala_Diag == 0);
  rtb_RelationalOperator10 = (*rtu_CellV_min > 2700);
  rtb_LogicalOperator10 = (rtb_RelationalOperator && ((!localDW->Relay1_Mode) &&
    localDW->Relay2_Mode) && rtb_RelationalOperator8 && rtb_LogicalOperator10 &&
    (*rtu_Flag_Charge) && rtb_RelationalOperator5 && rtb_RelationalOperator6 &&
    rtb_RelationalOperator7 && rtb_RelationalOperator2 &&
    rtb_RelationalOperator10);
  rtb_RelationalOperator7 = !*rtu_Flag_Charge;
  rtb_RelationalOperator3 = (*rtu_CellT_Max >= Cell_ThresholdTemp);
  rtb_RelationalOperator10 = (*rtu_CellV_min <= 2700);
  rtb_RelationalOperator = ((!rtb_RelationalOperator5) ||
    rtb_RelationalOperator7 || (*rtu_CollectChip_Temperature_Fla != 0) ||
    (!rtb_RelationalOperator8) || (!rtb_RelationalOperator) ||
    rtb_RelationalOperator3 || (!rtb_RelationalOperator6) ||
    (!rtb_RelationalOperator2) || rtb_RelationalOperator10);
  rtb_Add = (uint16_T)((uint32_T)*rtu_CellV_min + Threshold_DiffVoltage);
  for (i = 0; i < 32; i++) {
    rtb_LogicalOperator5_a[i] = (rtu_Cell_Voltage_mV[i] >= rtb_Add);
  }

  rtb_RelationalOperator8 = (*rtu_Balance_State == 0U);
  if (localDW->is_active_c3_Balance == 0U) {
    localDW->is_active_c3_Balance = 1U;
    localDW->Count_Flag = 0U;
    localDW->is_c3_Balance = Balance_IN_BalanceOff;
    for (i = 0; i < 32; i++) {
      localB->Flag_Balance[i] = OFF[i];
    }

    localDW->Count = 0U;
  } else if (localDW->is_c3_Balance == Balance_IN_BalanceOff) {
    if ((rtb_LogicalOperator10 || (*rtu_Balance_Ena)) && (localDW->Count >= 8) &&
        rtb_RelationalOperator8) {
      localDW->Count = 0U;
      localDW->is_c3_Balance = Balance_IN_BalanceOn;
      i = localDW->Count_Flag + 1;
      if (localDW->Count_Flag + 1 > 255) {
        i = 255;
      }

      localDW->Count_Flag = (uint8_T)i;
    } else {
      if (localDW->Count < 255) {
        i = localDW->Count + 1;
        if (localDW->Count + 1 > 255) {
          i = 255;
        }

        localDW->Count = (uint8_T)i;
      } else {
        localDW->Count = 0U;
      }

      if (localDW->Count_Flag == 4) {
        localDW->Count_Flag = 0U;
      }
    }
  } else if ((rtb_RelationalOperator && (!*rtu_Balance_Ena)) || (localDW->Count >=
              8)) {
    localDW->is_c3_Balance = Balance_IN_BalanceOff;
    for (i = 0; i < 32; i++) {
      localB->Flag_Balance[i] = OFF[i];
    }

    localDW->Count = 0U;
  } else {
    i = localDW->Count + 1;
    if (localDW->Count + 1 > 255) {
      i = 255;
    }

    localDW->Count = (uint8_T)i;
    if (localDW->Count_Flag == 1) {
      for (i = 0; i < 32; i++) {
        localB->Flag_Balance[i] = (rtb_LogicalOperator5_a[i] &&
          Balance_ON_Off_First[i]);
      }
    }

    if (localDW->Count_Flag == 2) {
      for (i = 0; i < 32; i++) {
        localB->Flag_Balance[i] = (rtb_LogicalOperator5_a[i] &&
          Balance_ON_Off_Second[i]);
      }
    }

    if (localDW->Count_Flag == 3) {
      for (i = 0; i < 32; i++) {
        localB->Flag_Balance[i] = (rtb_LogicalOperator5_a[i] &&
          Balance_ON_Off_Third[i]);
      }
    }

    if (localDW->Count_Flag == 4) {
      for (i = 0; i < 32; i++) {
        localB->Flag_Balance[i] = (rtb_LogicalOperator5_a[i] &&
          Balance_ON_Off_Forth[i]);
      }
    }
  }

  for (i = 0; i < 32; i++) {
    rtb_RelationalOperator = (localB->Flag_Balance[i] && rtu_CellVConnect_flg[i]);
    rtb_Bal_Cmd[i] = (int8_T)rtb_RelationalOperator;
    rtb_LogicalOperator5_a[i] = rtb_RelationalOperator;
  }

  localDW->UnitDelay_DSTATE = 0U;
  for (i = 0; i < 32; i++) {
    *rty_EN_Balance = ((uint32_T)rtb_Bal_Cmd[i] << (i + 1)) +
      localDW->UnitDelay_DSTATE;
    localDW->UnitDelay_DSTATE = *rty_EN_Balance;
  }

  if (localDW->is_active_c1_Balance == 0U) {
    localDW->is_active_c1_Balance = 1U;
    localDW->Local_State = *rty_EN_Balance;
    Rte_Write_Balance_Cmd(*rty_EN_Balance);
  } else if ((localDW->Local_State != *rty_EN_Balance) || (*rtu_Balance_State !=
              *rty_EN_Balance)) {
    localDW->Local_State = *rty_EN_Balance;
    Rte_Write_Balance_Cmd(*rty_EN_Balance);
  }

  *rty_Bal_State = (uint8_T)(*rty_EN_Balance != 0U);
  for (i = 0; i < 32; i++) {
    rty_Flag_Balance[i] = rtb_LogicalOperator5_a[i];
  }
}

void Balance_initialize(const char_T **rt_errorStatus, RT_MODEL_Balance_T *const
  Balance_M)
{
  rtmSetErrorStatusPointer(Balance_M, rt_errorStatus);
}
